package com.baayso.bms2.config.spring.web;

import org.slf4j.Logger;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.baayso.bms2.core.log.Log;

/**
 * Spring MVC 配置。
 * 
 * @author ChenFangjie(2015年9月19日 下午9:35:06)
 * 
 * @since 1.0.0
 * 
 * @version 1.0.0
 * 
 */
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.baayso.bms2", useDefaultFilters = false, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = { Controller.class, ControllerAdvice.class }) })
public class MvcConfig extends WebMvcConfigurationSupport {

    private static final Logger log = Log.get();

    /** 注册试图处理器 */
    @Bean
    public ViewResolver viewResolver() {
        log.info("ViewResolver");

        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

    /** 注册消息资源处理器 */
    @Bean
    public MessageSource messageSource() {
        log.info("MessageSource");

        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("config.messages.messages");

        return messageSource;
    }

    /** 注册servlet适配器，只需要在自定义的servlet上用 @Controller("映射路径") 标注即可 */
    @Bean
    public HandlerAdapter servletHandlerAdapter() {
        log.info("HandlerAdapter");

        return new SimpleServletHandlerAdapter();
    }

    /** 本地化拦截器 */
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        log.info("LocaleChangeInterceptor");

        return new LocaleChangeInterceptor();
    }

    /** 基于cookie的本地化资源处理器 */
    @Bean(name = "localeResolver")
    public CookieLocaleResolver cookieLocaleResolver() {
        log.info("CookieLocaleResolver");

        return new CookieLocaleResolver();
    }

    // /** 注册自定义拦截器 */
    // @Bean
    // public CP_InitializingInterceptor initializingInterceptor() {
    // logger.info("CP_InitializingInterceptor");
    // // HandlerInterceptor
    // return new CP_InitializingInterceptor();
    // }

    /** RequestMappingHandlerMapping需要显示声明，否则不能注册自定义的拦截器。这个比较奇怪，理论上应该是不需要的 */
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        log.info("RequestMappingHandlerMapping");

        return super.requestMappingHandlerMapping();
    }

    /** HandlerMapping需要显示声明，否则不能注册资源访问处理器。这个比较奇怪，理论上应该是不需要的 */
    @Bean
    public HandlerMapping resourceHandlerMapping() {
        log.info("HandlerMapping");

        return super.resourceHandlerMapping();
    }

    /** 文件上传处理器 */
    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver commonsMultipartResolver() {
        log.info("CommonsMultipartResolver");

        return new CommonsMultipartResolver();
    }

    // /** 异常处理器，系统运行时遇到指定的异常将会跳转到指定的页面 */
    // @Bean(name = "exceptionResolver")
    // public CP_SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
    // logger.info("CP_SimpleMappingExceptionResolver");
    //
    // CP_SimpleMappingExceptionResolver simpleMappingExceptionResolver = new CP_SimpleMappingExceptionResolver();
    // simpleMappingExceptionResolver.setDefaultErrorView("common_error");
    // simpleMappingExceptionResolver.setExceptionAttribute("exception");
    // Properties properties = new Properties();
    // properties.setProperty("java.lang.RuntimeException", "common_error");
    // simpleMappingExceptionResolver.setExceptionMappings(properties);
    //
    // return simpleMappingExceptionResolver;
    // }

    /** RequestMappingHandlerAdapter需要显示声明，否则不能注册通用属性编辑器。这个比较奇怪，理论上应该是不需要的 */
    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        log.info("RequestMappingHandlerAdapter");

        return super.requestMappingHandlerAdapter();
    }

    @Override
    protected void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController("/", "/index");
    }

    /** 添加拦截器 */
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        log.info("addInterceptors start...");

        registry.addInterceptor(localeChangeInterceptor());
        // registry.addInterceptor(initializingInterceptor());

        log.info("addInterceptors end.");
    }

    /** 资源访问处理器，可以在jsp中使用/static/**的方式访问/WEB-INF/static/下的内容 */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("addResourceHandlers");

        // registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/static/");
        registry.addResourceHandler("/jsp/**").addResourceLocations("/WEB-INF/views/jsp/");
    }

    /** 注册通用属性编辑器 */
    @Override
    protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
        log.info("ConfigurableWebBindingInitializer");

        ConfigurableWebBindingInitializer initializer = super.getConfigurableWebBindingInitializer();
        // CP_PropertyEditorRegistrar register = new CP_PropertyEditorRegistrar();
        // register.setFormat("yyyy-MM-dd");
        // initializer.setPropertyEditorRegistrar(register);

        return initializer;
    }

}
